/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#include "ak_obj.h"
#include "ak_evt.h"
#include "ak_step.h"
#include "ak_gears.h"

/* Trace Lvl */
static 	int 	_gTraceLvl_SStep = TRACELVL_NORMAL;

int 	SStep_SetTraceLvl(int lvl)
{
	int 	ret = -1;
	
	switch(lvl){
		case TRACELVL_FATAL:
		case TRACELVL_ERROR:
		case TRACELVL_WARNING:
		case TRACELVL_NORMAL:
		case TRACELVL_DEBUG:
		case TRACELVL_ALL:
			_gTraceLvl_SStep = lvl;
			ret = 0;
			break;
		default:
			break;
	}

	return ret;
}

int 	SStep_GetTraceLvl(void)
{
	return  _gTraceLvl_SStep;
}



#define SSTEP_TIMER_START(pDesc, pTimer) \
	do{\
		if((pDesc)->toDur){\
			/* Set the Interval, Event Type */\
			STimer_SetIntv(pTimer, (pDesc)->toDur);\
			(pTimer)->cbEntry.lArg = 0;\
			STimer_Start(pTimer);\
		}\
	}while(0)

#define SSTEP_TIMEOUT(pProc, ppDesc, pDesc, pArg, step, ret) \
	do{\
		(ppDesc) += step; \
		if((ppDesc) && (pDesc=*ppDesc) && ((pDesc)->TimeOut)){\
			ret = (pDesc)->TimeOut(pProc, pArg);	\
		}\
	}while(0)

#define SSTEP_EVTHDL(pProc, ppDesc, pDesc, pArg, step, ret, pEvent) \
	do{\
		(ppDesc) += step; \
		if((ppDesc) && (pDesc=*ppDesc) && ((pDesc)->EvtHdl)){\
			ret = (pDesc)->EvtHdl(pProc, pArg, pEvent);	\
		}\
	}while(0)


#define SSTEP_UNDO(pProc, ppDesc, pStep, pArg, step) \
	do{\
		(ppDesc) += step;\
		while(step > 0){\
			--(step);\
			--(ppDesc);\
			if((ppDesc) && (pStep=*ppDesc) && ((pStep)->Undo)){\
				(pStep)->Undo(pProc, pArg);	\
			}\
		};\
	}while(0)

#define SSTEP_DO(pProc, ppDesc, pDesc, pArg, step, ret) \
	do{\
		(ppDesc) += step; \
		if((ppDesc) && (pDesc=*ppDesc) && ((pDesc)->Do)){\
			SSTEP_TIMER_START(pDesc, pTimer);\
			ret = (pDesc)->Do(pProc, pArg);	\
		}\
	}while(0)

#define SSTEP_DUR(pProc, pDur)	\
	do{\
		STIMING_END((pProc)->timing);	\
		(pProc)->timing.diff /= 1000;	\
		(pDur)->total+= 1;				\
		if((pProc)->timing.diff < (pDur)->minDur){	\
			(pDur)->minDur = (pProc)->timing.diff;	\
		}else if((pProc)->timing.diff	> (pDur)->maxDur){\
			(pDur)->maxDur = (pProc)->timing.diff;	\
		}\
		(pDur)->sumDur += (pProc)->timing.diff; 	\
		(pDur)->avgDur	= (pDur)->sumDur / (pDur)->total;\
	}while(0)

#define SSTEP_INIT(pProc, pDesc, pTimer) \
	do{\
		if((pDesc)->Init){\
			(pDesc)->Init(pProc);\
		}\
		STimer_Stop(pTimer);\
	}while(0)

#define SSTEP_FINI_SUCC(pProc, pDesc, pTimer) \
	do{\
		STimer_Stop(pTimer);\
		if((pDesc)->Fini){\
			(pDesc)->Fini(pProc, SPROC_SUCC);\
		}\
		pDur = &(pStat->succ);\
		SSTEP_DUR(pProc, pDur);\
	}while(0)

#define SSTEP_FINI_FAIL(pProc, pDesc, pTimer) \
	do{\
		STimer_Stop(pTimer);\
		if((pDesc)->Fini){\
			(pDesc)->Fini(pProc, SPROC_FAIL);\
		}\
		pDur = &(pStat->fail);\
		SSTEP_DUR(pProc, pDur);\
	}while(0)

#define SSTEP_PRE_JUDGE(pProc, pDesc, pTimer) \
	do{\
		if((pProc)->step == -1){\
			SSTEP_INIT(pProc, pDesc,  pTimer);\
			STIMING_BEG((pProc)->timing);\
			(pProc)->bState = STEP_ST_PROC;\
		}\
	}while(0)

#define SSTEP_POST_JUDGE(pProc, pDesc, pTimer, ret) \
	do{\
		switch(ret){\
			case STEP_RET_FAIL:\
				/* Undo */ \
				ret = _SStep_Undo(pProc, pStat);\
				break;\
			case STEP_RET_SUCC:\
				if((pProc)->step == (pDesc)->total - 1){\
					/* Fini */\
					SSTEP_FINI_SUCC(pProc, pDesc,  pTimer);\
					(pProc)->bState = STEP_ST_FINI;\
				}\
				break;\
			default:\
				break;\
		}\
	}while(0)
		
		

static 	int 	_SStep_Exception(_t_sProcNode * pProc)
{
	_t_sProcDesc	*	pProcDesc;
	if(pProc && (pProcDesc = pProc->pDesc)){
		if(pProcDesc->Exception){
			pProcDesc->Exception(pProc);
		}
		pProc->step = -1;
	}
	return STEP_RET_FAIL;
}


static 	int 	_SStep_Undo(_t_sProcNode * pProc, _t_sStepStat * pStat)
{
	_t_sStepDesc	** 	ppDesc;
	_t_sProcDesc	* 	pProcDesc;
	_t_sStepDesc	* 	pStepDesc;
	STimer_Node 	* 	pTimer;
	_t_sStepDur		* 	pDur;
	void 			* 	pArg;
	int 		 		step, ret;

	ret = STEP_RET_UNK;
	if(	pProc && (pProcDesc = pProc->pDesc) && (ppDesc = pProcDesc->ppDesc)){
		step 	= pProc->step;
		pTimer 	= &(pProc->tNode);
		pArg 	= pProc->pArg;

		STimer_Stop(pTimer);

		/* Judge the Step */
		if((step >= 0) && (step < pProcDesc->total)){
			SSTEP_UNDO(pProc, ppDesc, pStepDesc, pArg, step);
			SSTEP_FINI_FAIL(pProc, pProcDesc,  pTimer);
			pProc->bState = STEP_ST_FINI;
		}
		else if(step != -1){
			ret = _SStep_Exception(pProc);
		}
				
		pProc->step = -1;
	}

	return ret;
}


static 	int 	_SStep_Do(_t_sProcNode * pProc)
{
	_t_sStepDesc	** 	ppDesc;
	_t_sStepDesc	* 	pStepDesc;
	_t_sProcDesc	* 	pProcDesc;
	STimer_Node 	* 	pTimer;
	void 			* 	pArg;
	int 		 		step, ret;

	ret = STEP_RET_UNK;
	if(	pProc && (pProcDesc = pProc->pDesc) && (ppDesc = pProcDesc->ppDesc)){
		pTimer 	= &(pProc->tNode);
		step 	= pProc->step;
		pArg 	= pProc->pArg;

		STimer_Stop(pTimer);
		/* Judge the Step */
		
		if((step >= 0) && (step < pProcDesc->total)){
			/* Proceeding */
			SSTEP_DO(pProc, ppDesc, pStepDesc, pArg, step, ret);
		}
		else{
			ret = _SStep_Exception(pProc);
		}

	}

	return ret;
}

static  int 	_SStep_TimeOut(_t_sProcNode * pProc)
{
	_t_sStepDesc	**	ppDesc;
	_t_sStepDesc	*	pStepDesc;
	_t_sProcDesc	*	pProcDesc;
	void 			* 	pArg;
	int 				step, ret;

	ret = STEP_RET_UNK;
	if(	pProc && (pProcDesc = pProc->pDesc) && (ppDesc = pProcDesc->ppDesc)){
		step 	= pProc->step;
		pArg 	= pProc->pArg;
		
		if((step >= 0) && (step < pProcDesc->total)){
			SSTEP_TIMEOUT(pProc, ppDesc, pStepDesc, pArg, step, ret);
		}else{
			ret = _SStep_Exception(pProc);
		}
	}
	return ret;
}

static  int 	_SStep_EvtHdl(_t_sProcNode * pProc, 	void * pEvent)
{
	_t_sStepDesc	**	ppDesc;
	_t_sStepDesc	*	pStepDesc;
	_t_sProcDesc	*	pProcDesc;
	void 			* 	pArg;
	int 				step, ret;

	ret = STEP_RET_UNK;
	if(	pProc && (pProcDesc = pProc->pDesc) && (ppDesc = pProcDesc->ppDesc)){
		step 	= pProc->step;
		pArg 	= pProc->pArg;
		
		if((step >= 0) && (step < pProcDesc->total)){
			SSTEP_EVTHDL(pProc, ppDesc, pStepDesc, pArg, step, ret, pEvent);
		}
	}
	return ret;
}

static 	int 	_SStep_Block(_t_sProcNode * pProc)
{
	_t_sStepDesc	** 	ppDesc;
	_t_sStepDesc	* 	pStepDesc;
	_t_sProcDesc	* 	pProcDesc;

	STimer_Node 	* 	pTimer;
	void 			* 	pArg;
	int 		 		step, ret;

	ret = STEP_RET_UNK;
	if(	pProc && (pProcDesc = pProc->pDesc) && (ppDesc = pProcDesc->ppDesc)){
		step 	= pProc->step;
		pTimer 	= &(pProc->tNode);
		pArg 	= pProc->pArg;

		/* Judge the Step */
		if((step >= 0) && (step < pProcDesc->total)){
			/* Undo */
			STimer_Stop(pTimer);

			ppDesc += step;
			if((ppDesc) && (pStepDesc=*ppDesc)  && (pStepDesc->Undo)){
				ret = pStepDesc->Undo(pProc, pArg);	
			}
		}
		else{
			ret = _SStep_Exception(pProc);
		}

	}

	return ret;
}


static 	int 	_SProcNode_OP(_t_sProcSche * pSche, _t_sProcNode * pProc, int op, void * pArg)
{
	int 				ret;
	_t_sProcDesc		* 	pProcDesc;
	_t_sStepStat		* 	pStat;
	_t_sStepDur			* 	pDur;
	STimer_Node 		* 	pTimer;
	
	ret = STEP_RET_UNK;
	if(pSche && pProc){
		pProcDesc 	= pProc->pDesc;
		pTimer 	  	= &(pProc->tNode);
		pStat		= pSche->pStat->sstat + pProcDesc->id;
		
		switch(op){
			case STEP_OP_DO:
				if(pProc->bBlock == 0){
					/* Prefix */
					SSTEP_PRE_JUDGE(pProc, pProcDesc, pTimer);

					/* Proceeding */
					pProc->step += 1;
					ret = _SStep_Do(pProc);

					/* Postfix */
					SSTEP_POST_JUDGE(pProc, pProcDesc, pTimer, ret);
				}
				break;

			case STEP_OP_UNDO:
				if(pProc->bBlock == 0){
					ret = _SStep_Undo(pProc, pStat);
				}
				break;
				
			case STEP_OP_BLOCK:
				if(pProc->step != -1){
					pProc->bBlock = 1;
					ret = _SStep_Block(pProc);
					pProc->bState = STEP_ST_PROC;

					/* Stat */
					pStat->block += 1;
				}
				break;

			case STEP_OP_UNBLOCK:
				if(pProc->step != -1){
					pProc->bBlock = 0;
					pProc->bState = STEP_ST_PROC;

					/* Proceeding */
					ret = _SStep_Do(pProc);
					/* Postfix */
					SSTEP_POST_JUDGE(pProc, pProcDesc, pTimer, ret);

					/* Stat */
					pStat->unblock += 1;
				}
				break;
				
			case STEP_OP_TIMEOUT:
				pStat->timeout += 1;
				if(pProc->step != -1){
					ret = _SStep_TimeOut(pProc);
					/* Postfix */
					SSTEP_POST_JUDGE(pProc, pProcDesc, pTimer, ret);
				}
				break;

			case STEP_OP_EVTHDL:
				pStat->timeout += 1;
				if(pProc->step != -1){
					ret = _SStep_EvtHdl(pProc, pArg);
					/* Postfix */
					SSTEP_POST_JUDGE(pProc, pProcDesc, pTimer, ret);
				}
				break;
				
			case STEP_OP_TEMINATE:
				pProc->bBlock = 0;
				ret = _SStep_Undo(pProc, pStat);

				/* Stat */
				pStat->terminate += 1;
				break;
			
			default:
				pProc->bBlock = 1;
				pProc->bState = STEP_ST_UNK;
				break;
		}
	}

	return ret;
}

static	int 	_SProcNode_TimeOut(_t_sProcNode * pProc, long lArg)
{
	int 				ret;
	_t_sProcSche	*	pSche;

	ret = STEP_RET_FAIL;
	if(pProc && (pSche = (pProc->pSche)) ){
		ret = SProcNode_Go(pSche, pProc, STEP_OP_TIMEOUT, NULL);
	}
	return ret;
}
				
static	int 	_SProcNode_EvtHdl(_t_sProcNode * pProc, void * pEvent)
{
	int 				ret;
	_t_sProcSche	*	pSche;

	ret = STEP_RET_UNK;
	if(pProc && (pSche = (pProc->pSche)) ){
		ret = SProcNode_Go(pSche, pProc, STEP_OP_EVTHDL, pEvent);
	}
	return ret;
}
								



/* -----------------------------------------------------------------------------
** Proc Pool Support 
*/
int 		SProcPool_Init(_t_sProcPool * pPool, unsigned int count)
{
	_t_sysMHeap	* mHeap;
	_t_sysMPool * mPool;
	_t_sysMSlot * mSlot;
	unsigned int 	mSize;
	unsigned long 	mLimit;
	
	if(pPool && (count > 0)){
		/* Default Increment by 1/2 */
		mHeap = &(pPool->mHeap);
		mPool = &(pPool->mPool);
		mSlot = &(pPool->mSlot);
		/* Init the Pool */
		mSize 	= sizeof(_t_sProcNode);
		mLimit 	= count * mSize;
		MHeap_InitEx(mHeap, mLimit);
		MPool_Init(mPool, mHeap, mLimit, mSize, 1,	 1,	MPOOL_T_SIMP);

		/* Init the Slot */
		MPOOL_SET_SLOT(mPool, mSlot);
		MSlot_Init(mSlot, mPool, 0, mSize);
		return 0;
	}

	return -1;
	
}

static 	_t_sProcNode *		_SProc_PoolAlloc(_t_sProcPool * pPool)
{
	if(pPool){
		return (_t_sProcNode *)MPool_AllocSi(&(pPool->mPool));
	}
	return NULL;
}

static 	int 		_SProc_PoolFree(_t_sProcPool * pPool, _t_sProcNode * pNode)
{
	if(pPool && pNode){
		return MPool_FreeSi(&(pPool->mPool), (void *)pNode);
	}
	return -1;
}


/* -----------------------------------------------------------------------------
** Proc Sche Support 
*/

int 	SProcSche_Init(_t_sProcSche * pSche, _t_sProcPool * pPool, STimer_Svr * pTSvr, _t_sProcStat * pStat)
{
	int 		i, ret;
	_t_blist * 	pQue;
	
	ret = -1;
	if(pSche && pPool && pStat){
		pSche->pPool = pPool;
		pSche->pStat = pStat;
		pSche->pTSvr = pTSvr;

		/* Lock & Que */
		SYS_INIT_CS(&(pSche->lock));
		pQue = pSche->priQue;
		for(i=0; i<SPROC_PRI_MAX; i++, pQue++){
			BLIST_INIT(pQue);
		}
		ret = 0;
	}
	return ret;
}

static 	int 	_SProcSche_Del(_t_sProcSche * pSche, _t_sProcNode * pProc)
{
	int pri;
	if(pSche && pProc){
		pri = pProc->priority;
		SYS_ENTER_CS(&(pSche->lock));
		BLST_DEL(pSche->priQue + pri, &(pProc->sNode));
		pProc->bState = STEP_ST_IDLE;
		SYS_LEAVE_CS(&(pSche->lock));
		return 0;
	}
	return -1;
}


static 	int 	_SProcSche_Add(_t_sProcSche * pSche, _t_sProcNode * pProc)
{
	int 	pri;
	if(pSche && pProc){
		pri = pProc->priority;
		SYS_ENTER_CS(&(pSche->lock));
		BLST_ADD2T(pSche->priQue + pri, &(pProc->sNode));
		SYS_LEAVE_CS(&(pSche->lock));
		return 0;
	}
	return -1;
}


int 	SProcNode_Go(_t_sProcSche * pSche, _t_sProcNode * pProc, int bOP, void * pEvent)
{
	int 	ret, flag;

	ret = STEP_RET_UNK;
	
	if(pSche && pProc){
		switch(bOP){
			case STEP_OP_TEMINATE:
				ret = _SProcNode_OP(pSche, pProc, STEP_OP_TEMINATE, NULL);
				break;
				
			case STEP_OP_UNDO:
				ret = _SProcNode_OP(pSche, pProc, STEP_OP_UNDO, NULL);
				break;

			case STEP_OP_DO:
				do{
					flag	= 0;
					ret 	= _SProcNode_OP(pSche, pProc, STEP_OP_DO, NULL);
					switch(ret){
						case STEP_RET_SUCC:
							if(pProc->bState == STEP_ST_PROC){
								flag = 1;
							}
							break;
						default:
							break;
					}
				}while(flag == 1);
				break;

			case STEP_OP_BLOCK:
				ret = _SProcNode_OP(pSche, pProc, STEP_OP_BLOCK, NULL);
				break;

			case STEP_OP_UNBLOCK:
				ret = _SProcNode_OP(pSche, pProc, STEP_OP_UNBLOCK, NULL);
				break;

			case STEP_OP_TIMEOUT:
				ret = _SProcNode_OP(pSche, pProc, STEP_OP_TIMEOUT, NULL);
				do{
					flag	= 0;
					switch(ret){
						case STEP_RET_SUCC:
							if(pProc->bState == STEP_ST_PROC){
								ret 	= _SProcNode_OP(pSche, pProc, STEP_OP_DO, NULL);
								flag = 1;
							}
							break;
						default:
							break;
					}
				}while(flag == 1);
				break;

			case STEP_OP_EVTHDL:
				ret = _SProcNode_OP(pSche, pProc, STEP_OP_EVTHDL, pEvent);
				do{
					flag	= 0;
					switch(ret){
						case STEP_RET_SUCC:
							if(pProc->bState == STEP_ST_PROC){
								ret 	= _SProcNode_OP(pSche, pProc, STEP_OP_DO, NULL);
								flag = 1;
							}
							break;
						default:
							break;
					}
				}while(flag == 1);
				break;

			default:
				break;
		}

		switch(pProc->bState){
			case STEP_ST_FINI:
				_SProcSche_Del(pSche, pProc);
				_SProc_PoolFree(pSche->pPool, pProc);
				break;
				
			case STEP_ST_UNK:
				/* Teminate */
				_SProcNode_OP(pSche, pProc, STEP_OP_TEMINATE, NULL);
				
				_SProcSche_Del(pSche, pProc);
				_SProc_PoolFree(pSche->pPool, pProc);
				break;
			default:
				break;
		}
	}

	return 	ret;
}



static int 	SProcSche_Term(_t_sProcSche * pSche, _t_sProcNode * pProc)
{
	if(pSche && pProc){
		SProcNode_Go(pSche, pProc, STEP_OP_TEMINATE, NULL);
		return 0;
	}
	return -1;
}


int 	SProcSche_TermByID(_t_sProcSche * pSche, unsigned int procID, int (*fChk)())
{
	_t_sProcNode * 	pProc;
	_t_sProcNode * 	pNext;
	_t_sProcDesc * 	pDesc;
	long 			i, j;	
	_t_blist 	 * 	pQue;
	
	if(pSche){
		SYS_ENTER_CS(&(pSche->lock));
		pQue = pSche->priQue;
		for(i=0; i<SPROC_PRI_MAX; i++, pQue++){
			pProc=(_t_sProcNode *)(pQue->head);
			for(j=0; j<pQue->count; j++, pProc=pNext){
				pNext = (_t_sProcNode *)(pProc->sNode.next);
				/* Check If the Proc By ID */
				if(	(pDesc = pProc->pDesc) && (pDesc->id == procID)){
					if(	(fChk == NULL) || 
						(fChk && (fChk(pProc) == 0))){
						BLST_DEL(pQue, &(pProc->sNode));
						SProcSche_Term(pSche, pProc);
					}
				}
			}
		}
		SYS_LEAVE_CS(&(pSche->lock));
		return 0;
	}
	return -1;
}


int 	SProcSche_TermByMask(_t_sProcSche * pSche, unsigned int procMask, int (*fChk)())
{
	_t_sProcNode * 	pProc;
	_t_sProcNode * 	pNext;
	_t_sProcDesc * 	pDesc;
	long 			i, j;	
	_t_blist 	 * 	pQue;
	
	if(pSche){
		SYS_ENTER_CS(&(pSche->lock));
		pQue = pSche->priQue;
		for(i=0; i<SPROC_PRI_MAX; i++, pQue++){
			pProc=(_t_sProcNode *)(pQue->head);
			for(j=0; j<pQue->count; j++, pProc=pNext){
				pNext = (_t_sProcNode *)(pProc->sNode.next);
				/* Check If the Proc By ID */
				if(	(pDesc = pProc->pDesc) && ((pDesc->id & procMask) == procMask)){
					if(	(fChk == NULL) || 
						(fChk && (fChk(pProc) == 0))){
						BLST_DEL(pQue, &(pProc->sNode));
						SProcSche_Term(pSche, pProc);
					}
				}
			}
		}
		SYS_LEAVE_CS(&(pSche->lock));
		return 0;
	}
	return -1;
}


int 	SProcSche_TermAll(_t_sProcSche * pSche)
{
	_t_sProcNode * 	pProc;
	long 			i;	
	_t_blist 	 * 	pQue;
	
	if(pSche){
		SYS_ENTER_CS(&(pSche->lock));
		pQue = pSche->priQue;
		for(i=0; i<SPROC_PRI_MAX; i++, pQue++){
			while((pProc = (_t_sProcNode *)BLST_GET(pQue))){
				SProcSche_Term(pSche, pProc);
			}
		}
		SYS_LEAVE_CS(&(pSche->lock));
		return 0;
	}
	return -1;
}


int 	SProcSche_EvtHdl(_t_sProcSche * pSche, void * pEvent)
{
	_t_sProcNode * 	pProc;
	long 			i, j;	
	_t_blist 	 * 	pQue;
	int 			ret, flag;

	if(pSche){
		ret = STEP_RET_UNK;

		SYS_ENTER_CS(&(pSche->lock));
		flag = 1;
		pQue = pSche->priQue;
		for(i=0; i<SPROC_PRI_MAX; i++, pQue++){
			pProc = (_t_sProcNode *)(pQue->head);
			for(j=0; j<pQue->count; j++, pProc = (_t_sProcNode *)(pProc->sNode.next)){
				ret = _SProcNode_EvtHdl(pProc, pEvent);
				if(ret != STEP_RET_UNK){
					flag = 0;
					break;
				}
			}
			
			if(flag == 0){
				break;
			}
		}
		SYS_LEAVE_CS(&(pSche->lock));

		if(ret != STEP_RET_UNK){
			return 0;
		}
	}
	return -1;
}


#define SPROC_DEFAULT_TO 	1000
_t_sProcNode * 	SProcNode_Init(_t_sProcSche * pSche, _t_sProcDesc * pDesc, void * pArg, int priority)
{
	_t_sProcNode * 	pProc;
	_t_sProcPool * 	pPool;
	STimer_Svr 	 * 	pTSvr;
	STimer_Node  * 	pTimer;
	_t_cbentry 		cbEntry;
	
	if(pSche && pDesc && (pDesc->id <= SPROC_MAX_ID ) && (pPool = pSche->pPool) && (pTSvr = pSche->pTSvr)){		
		pProc = _SProc_PoolAlloc(pPool);
		if(pProc){
			pProc->pSche 	= pSche;
			pProc->pDesc	= pDesc;
			pProc->pArg 	= pArg;
			
			/* Priority */
			if(priority < SPROC_PRI_HIGH)
				priority = SPROC_PRI_HIGH;

			if(priority > SPROC_PRI_LOW)
				priority = SPROC_PRI_LOW;
		
			pProc->priority	= priority;

			/* Timer */
			pTimer = &(pProc->tNode);
			_CBENTRY_INIT(&cbEntry, _SProcNode_TimeOut, pProc, 0);
			STimer_Init(pTimer, pTSvr, &cbEntry, SPROC_DEFAULT_TO);

			/* User */
			SYS_MEMZERO(&(pProc->user), sizeof(_t_sProcUser));
			
			/* Variable */
			pProc->step 	= -1;
			pProc->bState 	= STEP_ST_IDLE;
			pProc->bBlock 	= 0;
			_SProcSche_Add(pSche, pProc);
			return pProc;
		}
	}

	return NULL;
}


